package com.study.cloud.gateway.core.filter.loadBalance;

import com.alibaba.fastjson.JSON;
import com.study.cloud.gateway.common.constants.FilterConst;
import com.study.cloud.gateway.common.enums.ResponseCode;
import com.study.cloud.gateway.common.exception.InstanceNotFoundException;
import com.study.cloud.gateway.common.request.GatewayRequest;
import com.study.cloud.gateway.common.rule.Rule;
import com.study.cloud.gateway.common.rule.ServiceInstance;
import com.study.cloud.gateway.core.context.GatewayContext;
import com.study.cloud.gateway.core.filter.Filter;
import com.study.cloud.gateway.core.filter.FilterInterface;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.Set;

/**
 * @author wangwancheng
 * @create 2025/7/20 18:19
 */
@Slf4j
@Filter(
        id = FilterConst.LOAD_BALANCE_FILTER_ID,
        name = FilterConst.LOAD_BALANCE_FILTER_NAME,
        order = FilterConst.LOAD_BALANCE_FILTER_ORDER
)
public class LoadBalanceFilter implements FilterInterface {
    @Override
    public void doFilter(GatewayContext context) throws Exception {
        String uniqueId = context.getUniqueId();
        //获取负载均衡规则
        IGatewayLoadBalanceRule balance = getLoadBalanceRule(context);
        //获取服务实例
        ServiceInstance instance = balance.choose(uniqueId);

        log.info("负载均衡器选择结果：ip:{} port:{}" , instance.getIp(),instance.getPort());
        GatewayRequest request = context.getRequest();
        if (instance != null && request != null){
            String host = instance.getIp() + ":" + instance.getPort();
            request.setModifyHost(host);
        }else {
            log.warn("no instance available for : {}", uniqueId);
            throw new InstanceNotFoundException(ResponseCode.SERVICE_INSTANCE_NOT_FOUND);
        }
    }

    /**
     * 获取负载均衡器
     * @param cxt
     * @return
     */
    private IGatewayLoadBalanceRule getLoadBalanceRule(GatewayContext cxt) {
        IGatewayLoadBalanceRule loadBalanceRule = null;
        Rule rule = cxt.getRule();
        if (rule != null) {
            //获取过滤器的配置
            Set<Rule.FilterConfig> filterConfigs = rule.getFilterConfigs();
            for (Rule.FilterConfig filterConfig : filterConfigs){
                if (filterConfig == null){
                    continue;
                }
                String filterId = filterConfig.getId();
                if (filterId.equals(FilterConst.LOAD_BALANCE_FILTER_ID)){
                    String config = filterConfig.getConfig();
                    String strategy = FilterConst.LOAD_BALANCE_STRATEGY_RANDOM;
                    if (StringUtils.isNotBlank( config)){
                        Map<String,String> mapTypeMap = JSON.parseObject(config, Map.class);
                        strategy = mapTypeMap.getOrDefault(FilterConst.LOAD_BALANCE_KEY,strategy);
                        switch ( strategy){
                            case FilterConst.LOAD_BALANCE_STRATEGY_RANDOM:
                                loadBalanceRule = RandomLoadBalanceRule.getInstance();
                                break;
                            case FilterConst.LOAD_BALANCE_STRATEGY_ROUND_ROBIN:
                                loadBalanceRule = RoundLoadBalanceRule.getInstance(rule.getServerId());
                                break;
                            default:
                                log.error("loadBalanceStrategy is error");
                                loadBalanceRule = RandomLoadBalanceRule.getInstance();
                                break;
                        }

                    }
                }
            }

        }
        return loadBalanceRule;
    }
}
